﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using CommonClasses;
using System.Collections.ObjectModel;
using System.Windows.Input;

namespace WpfCardGame.ViewModel
{
    class PokerViewModel : ViewModelBase
    {
        private int SwitchesLeft;
       
        private List<bool> cards_to_switch = new List<bool>();

        private PokerGame _Game = new PokerGame();
        public PokerGame Game
        {
            get
            {
                return _Game;
            }
            set
            {
                _Game = value;
                RaisePropertyChanged(() => Game);
            }
        }

        private ObservableCollection<Card> _DealersCards;
        public ObservableCollection<Card> DealersCards
        {
            get
            {
                return _DealersCards;
            }
            set
            {
                _DealersCards = value;
                RaisePropertyChanged(() => DealersCards);
            }
        }

        private ObservableCollection<Card> _PlayersCards;
        public ObservableCollection<Card> PlayersCards
        {
            get
            {
                return _PlayersCards;
            }
            set
            {
                _PlayersCards = value;
                RaisePropertyChanged(() => PlayersCards);
            }
        }

        private bool _NewGameButtonEnabled;
        public bool NewGameButtonEnabled
        {
            get
            {
                return _NewGameButtonEnabled;
            }
            set
            {
                _NewGameButtonEnabled = value;
                RaisePropertyChanged(() => NewGameButtonEnabled);
            }
        }

        private bool _DealButtonEnabled;
        public bool DealButtonEnabled
        {
            get
            {
                return _DealButtonEnabled;
            }
            set
            {
                _DealButtonEnabled = value;
                RaisePropertyChanged(() => DealButtonEnabled);
            }
        }

        private bool _SwitchButtonEnabled;
        public bool SwitchButtonEnabled
        {
            get
            {
                return _SwitchButtonEnabled;
            }
            set
            {
                _SwitchButtonEnabled = value;
                RaisePropertyChanged(() => SwitchButtonEnabled);
            }
        }

        private bool _StandButtonEnabled;
        public bool StandButtonEnabled
        {
            get
            {
                return _StandButtonEnabled;
            }
            set
            {
                _StandButtonEnabled = value;
                RaisePropertyChanged(() => StandButtonEnabled);
            }
        }

        private string _DealerTotal;
        public string DealerTotal
        {
            get
            {
                return _DealerTotal;
            }
            set
            {
                _DealerTotal = value;
                RaisePropertyChanged(() => DealerTotal);
            }
        }

        private string _PlayerTotal;
        public string PlayerTotal
        {
            get
            {
                return _PlayerTotal;
            }
            set
            {
                _PlayerTotal = value;
                RaisePropertyChanged(() => PlayerTotal);
            }
        }

        private string _Status;
        public string Status
        {
            get
            {
                return _Status;
            }
            set
            {
                _Status = value;
                RaisePropertyChanged(() => Status);
            }
        }

        private bool _PCard1;
        public bool PCard1
        {
            get
            {
                return _PCard1;
            }
            set
            {
                _PCard1 = value;
                RaisePropertyChanged(() => PCard1);
            }
        }

        private bool _PCard2;
        public bool PCard2
        {
            get
            {
                return _PCard2;
            }
            set
            {
                _PCard2 = value;
                RaisePropertyChanged(() => PCard2);
            }
        }

        private bool _PCard3;
        public bool PCard3
        {
            get
            {
                return _PCard3;
            }
            set
            {
                _PCard3 = value;
                RaisePropertyChanged(() => PCard3);
            }
        }

        private bool _PCard4;
        public bool PCard4
        {
            get
            {
                return _PCard4;
            }
            set
            {
                _PCard4 = value;
                RaisePropertyChanged(() => PCard4);
            }
        }

        private bool _PCard5;
        public bool PCard5
        {
            get
            {
                return _PCard5;
            }
            set
            {
                _PCard5 = value;
                RaisePropertyChanged(() => PCard5);
            }
        }

        private bool _CheckBoxesEnabled;
        public bool CheckBoxesEnabled
        {
            get
            {
                return _CheckBoxesEnabled;
            }
            set
            {
                _CheckBoxesEnabled = value;
                RaisePropertyChanged(() => CheckBoxesEnabled);
            }
        }        

        public Dictionary<int, string> CardHand = new Dictionary<int, string>();

        public ICommand NewGameCommand { get; private set; }
        public ICommand DealCommand { get; private set; }
        public ICommand SwitchCommand { get; private set; }
        public ICommand StandCommand { get; private set; }
        public ICommand SwitchIndexCommand { get; private set; }

        #region "Constructors"
        public PokerViewModel()
        {
            NewGameCommand = new RelayCommand(NewGameMethod);
            DealCommand = new RelayCommand(DealMethod);
            SwitchCommand = new RelayCommand(SwitchMethod);
            StandCommand = new RelayCommand(StandMethod);

            InitializeForm();          
        }
        #endregion

        public void InitializeForm()
        {            
            Status = "Press \"New Game\" to start.";

            NewGameButtonEnabled = true;
            DealButtonEnabled = false;
            SwitchButtonEnabled = false;
            StandButtonEnabled = false;
            CheckBoxesEnabled = false;

            CardHand.Add(1, "High Card");
            CardHand.Add(2, "Pair");
            CardHand.Add(3, "Two Pair");
            CardHand.Add(4, "3 of a Kind");
            CardHand.Add(5, "Straight");
            CardHand.Add(6, "Flush");
            CardHand.Add(7, "Full House");
            CardHand.Add(8, "4 of a Kind");
            CardHand.Add(9, "Straight Flush");
            CardHand.Add(10, "Royal Flush");
        }

        private void UncheckCardSelection()
        {
            PCard1 = false;
            PCard2 = false;
            PCard3 = false;
            PCard4 = false;
            PCard5 = false;
        }

        public void NewGameMethod()
        {
            // Subscribe to events.
            Game.PokerWinner += new PokerGame.PokerWinnerEventHandler(GameWinner);
            Game.NotEnoughCards += new PokerGame.NotEnoughCardsEventHandler(NotEnoughCardsToPlay);            

            Status = String.Empty;
            NewGameButtonEnabled = false;
            DealButtonEnabled = true;

            Game.NewGame();
            DealersCards = new ObservableCollection<Card>();
            PlayersCards = new ObservableCollection<Card>();

            Status = "Press \"Deal\" to begin.";
        }

        public void DealMethod()
        {
            SwitchesLeft = 3;

            Status = string.Empty;
            PlayerTotal = string.Empty;
            DealerTotal = string.Empty;

            DealButtonEnabled = false;
            SwitchButtonEnabled = true;
            StandButtonEnabled = true;
            CheckBoxesEnabled = true;
            UncheckCardSelection();

            Game.Deal();            
            DealersCards = Game.dealerHand.CardsInPlay();
            PlayersCards = Game.playerHand.CardsInPlay();
            
            if (Game.playerHand.Total.Count > 0)
            {
                PlayerTotal = CardHand[Game.playerHand.Total[0]];
            }                     
        }      

        public void SwitchMethod()
        {
            // Add checkboxes' state to a List<bool>.
            cards_to_switch.Clear();
            cards_to_switch.Add(PCard1);
            cards_to_switch.Add(PCard2);
            cards_to_switch.Add(PCard3);
            cards_to_switch.Add(PCard4);
            cards_to_switch.Add(PCard5);

            // Determine how many cards are selected.
            int selected_cards = 0;
            List<int> cards_to_remove = new List<int>();
            for (int i=0; i< cards_to_switch.Count; i++)
            {
                if (cards_to_switch[i] == true)
                {
                    selected_cards++;
                    cards_to_remove.Add(i);
                }
            }

            // Warn if number of selected cards exceed number of switches left and exit method.
            if (selected_cards > SwitchesLeft)
            {
                Status = String.Format("Maximum of {0} selected cards.", SwitchesLeft);
                return;
            }

            // Do card(s) switching.   
            Game.PlayerMove(cards_to_remove);
            PlayersCards = Game.playerHand.CardsInPlay();
            Game.playerHand.calculate_total();
            PlayerTotal = CardHand[Game.playerHand.Total[0]];

            UncheckCardSelection();           

            // Disable checkboxes and Switch button after switching.            
            CheckBoxesEnabled = false;
            SwitchButtonEnabled = false;            
        }

        public void StandMethod()
        {
            DealButtonEnabled = true;
            SwitchButtonEnabled = false;
            StandButtonEnabled = false;
            CheckBoxesEnabled = false;

            Game.DealerFaceUp();
            DealersCards = Game.dealerHand.CardsInPlay();
            Game.Evaluate();
            DealerTotal = CardHand[Game.dealerHand.Total[0]];
        }

        #region "EventMethods"
        public void GameWinner(string name, List<int> total)
        {

            Status = String.Format("Winner: {0}  Hand: {1}", name, CardHand[total[0]]);
        }

        public void NotEnoughCardsToPlay()
        {
            Game.playerHand = new PokerHand();
            Game.dealerHand = new PokerHand();            

            Status = string.Empty;
            PlayerTotal = string.Empty;
            DealerTotal = string.Empty;

            NewGameButtonEnabled = true;
            SwitchButtonEnabled = false;
            StandButtonEnabled = false;
            DealButtonEnabled = false;
            CheckBoxesEnabled = false;

            Status = "Not enough cards in Deck to play.";
        }
        #endregion
    }
}
